package services

import (
	"crypto/tls"
	"fmt"
	"net/smtp"
	"strconv"
	"sync"

	"enzyme-backend/core/utils"

	"github.com/gin-gonic/gin"
)

var (
	// Email 全局邮件服务实例
	GlobalEmail *EmailService
	emailOnce   sync.Once
)

// init 初始化邮件服务
func init() {
	emailOnce.Do(func() {
		// 从环境变量读取SMTP配置
		port, _ := strconv.Atoi(utils.GetEnv("SMTP_PORT", "587"))

		GlobalEmail = &EmailService{
			config: &EmailConfig{
				Host:     utils.GetEnv("SMTP_HOST", ""),
				Port:     port,
				Username: utils.GetEnv("SMTP_USERNAME", ""),
				Password: utils.GetEnv("SMTP_PASSWORD", ""),
				From:     utils.GetEnv("SMTP_FROM", ""),
			},
		}
		utils.GlobalLogger.Info("邮件服务已初始化")
	})
}

// EmailService 邮件服务
type EmailService struct {
	config *EmailConfig
}

// EmailConfig 邮件配置
type EmailConfig struct {
	Host     string
	Port     int
	Username string
	Password string
	From     string
}

// SendEmail 发送邮件
func (es *EmailService) sendEmail(to, subject, body string) error {
	// 如果邮件配置为空，则使用模拟发送
	if es.config.Host == "" || es.config.Username == "" {
		utils.GlobalLogger.Info("使用模拟发送邮件模式",
			"to", to,
			"subject", subject,
			"body", body)
		return nil
	}

	utils.GlobalLogger.Info("开始发送邮件",
		"host", es.config.Host,
		"port", es.config.Port,
		"from", es.config.From,
		"to", to)

	// 构建邮件头
	headers := make(map[string]string)
	headers["From"] = es.config.From
	headers["To"] = to
	headers["Subject"] = subject
	headers["MIME-Version"] = "1.0"
	headers["Content-Type"] = "text/html; charset=UTF-8"

	// 构建邮件内容
	message := ""
	for k, v := range headers {
		message += fmt.Sprintf("%s: %s\r\n", k, v)
	}
	message += "\r\n" + body

	// 发送邮件
	auth := smtp.PlainAuth("", es.config.Username, es.config.Password, es.config.Host)

	addr := fmt.Sprintf("%s:%d", es.config.Host, es.config.Port)

	// 根据端口选择是否使用TLS
	if es.config.Port == 587 {
		// 使用STARTTLS
		client, err := smtp.Dial(addr)
		if err != nil {
			utils.GlobalLogger.Error("连接邮件服务器失败",
				"error", err,
				"addr", addr)
			return fmt.Errorf("连接邮件服务器失败: %w", err)
		}
		defer client.Close()

		if err = client.StartTLS(&tls.Config{ServerName: es.config.Host}); err != nil {
			utils.GlobalLogger.Error("启动TLS失败",
				"error", err,
				"host", es.config.Host)
			return fmt.Errorf("启动TLS失败: %w", err)
		}

		if err = client.Auth(auth); err != nil {
			utils.GlobalLogger.Error("邮件认证失败",
				"error", err,
				"username", es.config.Username)
			return fmt.Errorf("邮件认证失败: %w", err)
		}

		if err = client.Mail(es.config.From); err != nil {
			utils.GlobalLogger.Error("设置发件人失败",
				"error", err,
				"from", es.config.From)
			return fmt.Errorf("设置发件人失败: %w", err)
		}

		if err = client.Rcpt(to); err != nil {
			utils.GlobalLogger.Error("设置收件人失败",
				"error", err,
				"to", to)
			return fmt.Errorf("设置收件人失败: %w", err)
		}

		w, err := client.Data()
		if err != nil {
			utils.GlobalLogger.Error("准备发送邮件失败",
				"error", err)
			return fmt.Errorf("准备发送邮件失败: %w", err)
		}
		defer w.Close()

		_, err = w.Write([]byte(message))
		if err != nil {
			utils.GlobalLogger.Error("发送邮件失败",
				"error", err)
			return fmt.Errorf("发送邮件失败: %w", err)
		}
	} else {
		// 直接发送
		err := smtp.SendMail(addr, auth, es.config.From, []string{to}, []byte(message))
		if err != nil {
			utils.GlobalLogger.Error("发送邮件失败",
				"error", err,
				"addr", addr)
			return fmt.Errorf("发送邮件失败: %w", err)
		}
	}

	utils.GlobalLogger.Info("邮件发送成功",
		"to", to,
		"subject", subject)
	return nil
}

// SendVerifyCode 发送验证码
func (es *EmailService) SendVerifyCode(c *gin.Context, to, code string) error {
	subject := "Enzyme验证码"
	body := fmt.Sprintf("您的验证码是: %s\n\n验证码3分钟内有效。", code)

	return es.sendEmail(to, subject, body)
}

// SendWelcomeEmail 发送欢迎邮件
func (es *EmailService) SendWelcomeEmail(email, username string) error {
	subject := "欢迎使用 Enzyme VPN"
	body := fmt.Sprintf(`
		<html>
		<body>
			<h2>欢迎使用 Enzyme VPN</h2>
			<p>亲爱的 %s，</p>
			<p>感谢您注册 Enzyme VPN！您的账户已成功创建。</p>
			<p>现在您可以开始使用我们的服务了。</p>
			<p>如有任何问题，请随时联系我们的客服团队。</p>
			<hr>
			<p style="color: #666; font-size: 12px;">此邮件由系统自动发送，请勿回复。</p>
		</body>
		</html>
	`, username)

	return es.sendEmail(email, subject, body)
}

// SendPasswordResetEmail 发送密码重置邮件
func (es *EmailService) SendPasswordResetEmail(email, password string) error {
	subject := "Enzyme VPN - 密码重置"
	body := fmt.Sprintf(`
		<html>
		<body>
			<h2>密码重置</h2>
			<p>您请求重置密码，新密码为：%s</p>
			<p>如果这不是您的操作，请忽略此邮件。</p>
			<hr>
			<p style="color: #666; font-size: 12px;">此邮件由系统自动发送，请勿回复。</p>
		</body>
		</html>
	`, password)

	return es.sendEmail(email, subject, body)
}
